package com.cwz.gateway.filter;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.cwz.core.utils.servle.ServletUtils;
import com.cwz.core.utils.string.StringUtils;
import com.cwz.gateway.config.properties.CaptchaProperties;
import com.cwz.gateway.service.ValidateCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @program: w-demo
 * @description: 验证码过滤器
 * 对于有些非通用的功能或者面向用户自定义的功能采用全局过滤器实现显然是不合理的，
 * 基于此出发开源作者变换了思路，采用工厂模式来即时生产一个自定义或者配置的过滤器来过滤当前的请求
 * @author: Wen
 **/
@Component
public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object> {
	@Autowired
	private ValidateCodeService validateCodeService;
	@Autowired
	private CaptchaProperties captchaProperties;

	private static final String CODE = "code";
	private static final String UUID = "uuid";
	private final static String[] VALIDATE_URL = new String[] { "/auth/login", "/auth/register" };

	@Override
	public GatewayFilter apply(Object config) {
		return (exchange, chain) -> {
			ServerHttpRequest request = exchange.getRequest();
			// 非登录/注册请求或验证码关闭，不处理
			if (!StringUtils.containsAnyIgnoreCase(request.getURI().getPath(), VALIDATE_URL) || !captchaProperties.getEnabled()) {
				return chain.filter(exchange);
			}
			try {
				String rspStr = resolveBodyFromRequest(request);
				JSONObject obj = JSON.parseObject(rspStr);
				validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID));
			} catch (Exception e) {
				return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage());
			}
			return chain.filter(exchange);
		};
	}

	/**
	 * @Description: 获取请求的正文
	 * @Author: Wen
	 * @param request:
	 * @return: java.lang.String
	 **/
	private String resolveBodyFromRequest(ServerHttpRequest request) {
		// 获取请求体
		Flux<DataBuffer> body = request.getBody();
		AtomicReference<String> bodyRef = new AtomicReference<>();
		body.subscribe(buffer -> {
			CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
			DataBufferUtils.release(buffer);
			bodyRef.set(charBuffer.toString());
		});
		return bodyRef.get();
	}

}
